﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CutAways.Geometry
{
	[Serializable]
	struct Interval
	{
		private float minimum;
		private float maximum;

		public static readonly Interval Empty     = new Interval(float.MaxValue, float.MinValue);
		public static readonly Interval ZeroZero = new Interval(0f, 0f);
		public static readonly Interval ZeroOne  = new Interval(0f, 1f);
		public static readonly Interval ZeroTwoPI = new Interval(0f, (float)(2.0 * Math.PI));

		public float Minimum
		{
			get { return minimum; }
			set { minimum = value; }
		}

		public float Maximum
		{
			get { return maximum; }
			set { maximum = value; }
		}

		public float Length
		{
			get { return maximum - minimum; }
		}

		public float Center
		{
			get { return minimum + Length / 2f; }
		}

		public void Join(float value)
		{
			if (this == Empty)
				minimum = maximum = value;
			else
			{
				if (value < minimum)
					minimum = value;
				if (value > maximum)
					maximum = value;
			}
		}

		public void Join(Interval interval)
		{
			if (interval == Empty)
				return;
			Join(interval.minimum);
			Join(interval.maximum);
		}

		public Interval(float minimum, float maximum)
		{
			this.minimum = minimum;
			this.maximum = maximum;
		}

		public bool Contains(float value)
		{
			return value >= minimum && value <= maximum;
		}

		public Interval IntersectionWith(Interval other)
		{
			if (HasIntersectionWith(other))
				return new Interval(Math.Max(this.minimum, other.minimum), Math.Min(this.maximum, other.maximum));
			return Interval.Empty;
		}

		public bool HasIntersectionWith(Interval other)
		{
			return this.Contains(other.minimum) || this.Contains(other.maximum) || other.Contains(this.minimum) || other.Contains(this.maximum);
		}

		public static bool operator ==(Interval a, Interval b)
		{
			return a.minimum == b.minimum && a.maximum == b.maximum;
		}

		public static bool operator !=(Interval a, Interval b)
		{
			return !(a == b);
		}

		/// <summary>
		/// rozsiri nebo zuzi interval podle stredu v zavislosti na faktoru, pokud je faktor 1, vrati se stejny interval
		/// </summary>
		public static Interval operator *(Interval interval, float factor)
		{
			return new Interval(interval.Center + (interval.minimum - interval.Center) * factor, interval.Center + (interval.maximum - interval.Center) * factor);
		}

		public override bool Equals(object obj)
		{
			return base.Equals(obj);
		}

		public override int GetHashCode()
		{
			return base.GetHashCode();
		}

		public override string ToString()
		{
			return "<" + minimum + "; " + maximum + ">";
		}
	}
}
